package com.javaweb.blogcite.service.Impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.javaweb.blogcite.common.PageData;
import com.javaweb.blogcite.controller.vo.BlogItemView;
import com.javaweb.blogcite.controller.vo.BlogView;
import com.javaweb.blogcite.mapper.BlogMapper;
import com.javaweb.blogcite.mapper.BlogTypeMapper;
import com.javaweb.blogcite.mapper.CommentMapper;
import com.javaweb.blogcite.pojo.Blog;
import com.javaweb.blogcite.pojo.BlogType;
import com.javaweb.blogcite.pojo.Toc;
import com.javaweb.blogcite.pojo.Comment;
import com.javaweb.blogcite.service.BlogService;
import com.javaweb.blogcite.util.TocGenerator;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class BlogServiceImpl implements BlogService {
    @Resource
    private BlogMapper blogMapper;

    @Resource
    private BlogTypeMapper blogTypeMapper;

    @Resource
    private CommentMapper commentMapper;

    @Override
    public BlogView getBlogById(Integer id) {
        Blog blog = blogMapper.selectById(id);
        if (blog == null) {
            return null;
        }
        Integer categoryId = blog.getCategoryId();
        BlogType category = blogTypeMapper.selectBlogTypeById(categoryId);
        // 更新 scan_number
        blog.setScanNumber(blog.getScanNumber() + 1);
        UpdateWrapper<Blog> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", id).set("scan_number", blog.getScanNumber());
        blogMapper.update(null, updateWrapper);
        return new BlogView(blog, category);
    }

    @Override
    public Boolean deleteBlogById(Integer id) {
        // 根据 Blog 的 category_id，找到 blog_type 表中对应的记录，将 blog_count 减一
        Blog blog = blogMapper.selectById(id);
        BlogType blogType = blogTypeMapper.selectBlogTypeById(blog.getCategoryId());
        UpdateWrapper<BlogType> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", blogType.getId()).set("blog_count", blogType.getBlogCount() - 1);
        blogTypeMapper.update(null, updateWrapper);

        // 根据 Blog 的 id，将 comment 表中对应的记录全部删除（删除该文章下的所有评论）
        commentMapper.delete(new QueryWrapper<Comment>().eq("blog_id", id));

        int rows = blogMapper.deleteById(id);
        return rows > 0;
    }


    @Override
    public PageData<BlogItemView> getBlogByPage(Integer page, Integer limit, Integer categoryId) {
        if (categoryId == -1) {
            // 查询全部
            Page<Blog> pageHelper = new Page<>(page, limit);
            IPage<Blog> blogIPage = blogMapper.selectPage(pageHelper, null);
            List<Blog> blogList = blogIPage.getRecords();
            List<BlogType> blogTypeList = blogTypeMapper.selectAllBlogType();

            List<BlogItemView> blogItemViews = new ArrayList<>();
            for (Blog blog : blogList) {
                Integer cid = blog.getCategoryId();
                BlogType type = null; // 无对应的分类
                for (BlogType blogType : blogTypeList) {
                    if (blogType.getId().equals(cid)) {
                        type = blogType;
                        break;
                    }
                }
                blogItemViews.add(new BlogItemView(blog, type));
            }
            return new PageData<>(blogIPage.getTotal(), blogItemViews);
        }

        IPage<Blog> pageHelper = new Page<>(page, limit);
        BlogType blogType = blogTypeMapper.selectBlogTypeById(categoryId);
        QueryWrapper<Blog> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("category_id", categoryId);
        IPage<Blog> blogIPage = blogMapper.selectPage(pageHelper, queryWrapper);
        List<Blog> records = blogIPage.getRecords();
        List<BlogItemView> blogItemViews = new ArrayList<>();
        for (Blog record : records) {
            BlogItemView blogItemView = new BlogItemView(record, blogType);
            blogItemViews.add(blogItemView);
        }

        return new PageData<>(blogIPage.getTotal(), blogItemViews);
    }

    @Override
    public Boolean updateBlog(Integer id, Blog blog) {
        int rows = 0;

        ObjectMapper objectMapper = new ObjectMapper();
        List<Toc> tocList = TocGenerator.generateTOC(blog.getHtmlContent());
        String tocString = null;
        try {
            tocString = objectMapper.writeValueAsString(tocList);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }

        // 根据原来的 categoryId, 更新 blog_type 中的 blog_count 字段
        Blog preBlog = blogMapper.selectById(id);
        BlogType blogType = blogTypeMapper.selectBlogTypeById(preBlog.getCategoryId());
        UpdateWrapper<BlogType> updateWrapper1 = new UpdateWrapper<>();
        updateWrapper1.eq("id", preBlog.getCategoryId()).set("blog_count", blogType.getBlogCount() - 1);
        blogTypeMapper.update(null, updateWrapper1);

        // 更新 blog
        UpdateWrapper<Blog> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", id)
                .set("title", blog.getTitle())
                .set("description", blog.getDescription())
                .set("thumb", blog.getThumb())
                .set("category_id", blog.getCategoryId())
                .set("html_content", blog.getHtmlContent())
                .set("toc", tocString);
        rows += blogMapper.update(null, updateWrapper);

        // 根据新的 categoryId, 更新 blog_type 中的 blog_count 字段
        BlogType blogType1 = blogTypeMapper.selectBlogTypeById(blog.getCategoryId());
        UpdateWrapper<BlogType> updateWrapper2 = new UpdateWrapper<>();
        updateWrapper2.eq("id", blog.getCategoryId()).set("blog_count", blogType1.getBlogCount() + 1);
        blogTypeMapper.update(null, updateWrapper2);

        return rows > 0;
    }

    @Override
    public boolean publishBlog(Blog blog) {
        int rows = 0;

        ObjectMapper objectMapper = new ObjectMapper();
        List<Toc> tocList = TocGenerator.generateTOC(blog.getHtmlContent());
        String tocString = null;
        try {
            tocString = objectMapper.writeValueAsString(tocList);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }

        Blog blog1 = new Blog();
        blog1.setToc(tocString);
        blog1.setTitle(blog.getTitle());
        blog1.setDescription(blog.getDescription());
        blog1.setThumb(blog.getThumb());
        blog1.setCreateDate(new Date().getTime());
        blog1.setHtmlContent(blog.getHtmlContent());
        blog1.setScanNumber(0);
        blog1.setCommentNumber(0);
        blog1.setId(blog.getId());
        blog1.setCategoryId(blog.getCategoryId());

        rows = blogMapper.insert(blog1);

        // 更新 blog_type 表的 blog_count 字段
        BlogType blogType = blogTypeMapper.selectBlogTypeById(blog.getCategoryId());
        blogType.setBlogCount(blogType.getBlogCount() + 1);
        blogTypeMapper.updateBlogType(blogType);
        return rows > 0;
    }
}
